Execution Techniques
The purpose of this section is to help aid an analyst in identifying different types of execution techniques that may be employed within an obfuscated PowerShell script. It critical to be able to identify the execution method in order to remove/disable it and defang the script so that it does not execute the malicious code during analysis.
Invoke-Expressionβ
Invoke-Expression (or IEX) simply takes in a string as input and executes it as a command. It is the most common execution method for obfuscated scripts, because the process of deobfuscating the script will almost always output a string - which cannot be executed directly.
Direct Executionβ
There are multiple ways that Invoke-Expression can be directly called:
-
In its direct form:
Invoke-Expression "<COMMANDS>"- Defanging: To render the above script harmless,
Invoke-Expressionmust be removed
- Defanging: To render the above script harmless,
-
In its aliased form:
IEX "<COMMANDS>"- Defanging: To render the above script harmless,
IEXmust be removed
- Defanging: To render the above script harmless,
-
With a command string piped into it:
"<COMMANDS>" | iex- Defanging: To render the above script harmless,
| iexmust be removed
- Defanging: To render the above script harmless,
-
Taking advantage of a leading
&to execute the following string as a command:&"iex" "<COMMANDS>"- Defanging: To render the above script harmless,
&"iex"must be removed
- Defanging: To render the above script harmless,
-
Taking advantage of a leading
.to execute the following string as a command:."iex" "<COMMANDS>"- Defanging: To render the above script harmless,
."iex"must be removed
- Defanging: To render the above script harmless,
IEX Obfuscationβ
The execution of IEX most commonly obfuscated by character indexing using existing strings from environment variables that should be the same throughout all Windows environment.
All of the following variations are expected to result in the same iex string (which must still be executed with either a leading . or & as shown in previous examples):
-
This looks for the only variable name that is expected to match the pattern
*mdr*:MaximumDriveCount(variable '*mdr*').name[3,11,2]-join'' -
This relies on the default
$VerbosePreferencevalue of:SilentlyContinue([string]$VerbosePreference)[1,3]+'x'-join'' -
This relies on the default
$PSHOMEvalue of:C:\Windows\System32\WindowsPowerShell\v1.0($PSHOME[21]+$PSHOME[30]+'x') -
This relies on the default
$ENV:ComSpecvalue of:C:\WINDOWS\system32\cmd.exe$ENV:ComSpec[4,24,25]-join''
[scriptblock]::create()β
Executing [scriptblock]::create("<COMMANDS>") alone will return a System.Management.Automation.ScriptBlock object, which is represented as a string, but no execution occurs. Execution via this method can be done with any of the following methods:
-
The
.Invoke()method of theSystem.Management.Automation.ScriptBlockobject is was initiates an execution:[scriptblock]::create("<COMMANDS>").Invoke()- Defanging: To render the above script harmless, the leading
[scriptblock]::create(and trailing).Invoke()must be removed
- Defanging: To render the above script harmless, the leading
-
Because
[scriptblock]::create()alone is treated like a string, a leading&can be used to execute the string as a command:&([scriptblock]::create("<COMMANDS>"))- Defanging: To render the above script harmless, the leading
&([scriptblock]::create(and trailing))must be removed
- Defanging: To render the above script harmless, the leading
-
Because
[scriptblock]::create()alone is treated like a string, a leading.can be used to execute the string as a command:.([scriptblock]::create("<COMMANDS>"))- Defanging: To render the above script harmless, the leading
.([scriptblock]::create(and trailing))must be removed
- Defanging: To render the above script harmless, the leading